/**Have to create database paye SQL query :CREATE DATABASE `paye` ;

  CREATE TABLE `paye`.`08-09` (
 `cin` INT( 11 ) NOT NULL ,
 `salBase` DECIMAL (7,3) NOT NULL ,
 `retenu` DECIMAL (7,3) NOT NULL ,
 `prime` DECIMAL (7,3) NOT NULL ,
 `salFinal` DECIMAL (7,3) NOT NULL ,
 `notes` TEXT NOT NULL
) ENGINE = MYISAM

  */

#include "ncreport.h"
#include "ncreportoutput.h"
#include "ncreportpreviewoutput.h"
#include "ncreportpreviewwindow.h"


/// @bug: employee deleteion isn't done from firts time ++ implment multi delete

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QMessageBox>
#include <QDebug>

#include <QSqlError>
#include <QSqlDatabase>
#include <QSqlQuery>

#include <QCompleter>


QSqlQuery current;
QSqlQuery operation;
QSqlQuery changes;
QSqlQuery fiche;
QString msg="%1 %2";
QStringList fields;
QString fieldOrder;
QString nom,prenom,cnss,cin,baseSal,poste,dateNais,ID;
//double baseSal;

QSqlDatabase db ;

bool dbConnOk=false;


QStringList nomList,prenomList,posteList;

QCompleter *nomComp,*prenomComp,*posteComp;

MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    fields<<"ID"<<"Nom"<<"Prenom"<<"CNSS"<<"CIN"<<"Salaire"<<"Poste";
    fieldOrder="ID";
    ///editMode=false;
    //ui->persoTable->setSortingEnabled(true);
    ui->persoTable->setSelectionBehavior(QAbstractItemView::SelectRows);
    /// resize coulumns
    ui->persoTable->setColumnWidth(0,35);
    ui->persoTable->setColumnWidth(1,130);
    ui->persoTable->setColumnWidth(4,80);
    ui->persoTable->setColumnWidth(5,70);
    ui->persoTable->setColumnWidth(6,90);
    ui->persoTable->setSelectionMode(QAbstractItemView::SingleSelection);
    ui->moisCB->setCurrentIndex(QDate::currentDate().month()-2);

    showMaximized();

    QCoreApplication::setOrganizationName("Alliance");
    QCoreApplication::setApplicationName("paye");

    QSettings s;
    if (s.contains("Designer/lastConnect")){
        m_connList = s.value("Designer/connections").toMap();
        map = m_connList[s.value("Designer/lastConnect").toString()].toMap();

    }
    else {
        QMessageBox::critical(0,"Premier lancement","C'est la première fois que vous lancez la paye. Veuillez configurer les paramètres d'abord!",QMessageBox::Ok);
        showSettings();
        /// @todo: have to restart the application now to save the connection settings
    }

    /// Create connections;
    connect(ui->actionDonn, SIGNAL(triggered()),this, SLOT( showSettings()));
    connect(ui->actionPrint, SIGNAL(triggered()),this, SLOT( print()));
    connect(ui->actionAbs_mois, SIGNAL(triggered()),this, SLOT(printAbsMois()));
    connect(ui->actionAbs_employ, SIGNAL(triggered()),this, SLOT(printAbsEmp()));
    connect(ui->actionPay_mois, SIGNAL(triggered()),this, SLOT( printPayMois()));
    connect(ui->actionPay_employ, SIGNAL(triggered()),this, SLOT(printPayEmp()));
    /// Add fields
    ui->triCB->addItems(fields);

}


void MainWindow::trier(QString field){
fieldOrder=field;
getRecords();

}




void MainWindow::printTable(QString repFile){

    NCReport *report = new NCReport();
    getValues();


    if (repFile=="abs.xml"){

        report->addParameter("dateSt",QDate::currentDate().toString(QString("yyyy-%2-%1").arg("1").arg(ui->moisCB->currentIndex()+1)));
        report->addParameter("dateEnd",QDate::currentDate().toString(QString("yyyy-%2-%1").arg("31").arg(ui->moisCB->currentIndex()+1)));
        report->addParameter("month",ui->moisCB->currentText());
        QStringList listNoms;listNoms<<"amin|ter";
        listNoms<<"mehdi";
        report->addStringList(listNoms,"noms");
    }

    if (repFile=="absEmp.xml" || repFile=="payEmp.xml" ){
        if (cin==""){
            QMessageBox::critical(0,"Impossible","Veuillez sélectionner un ouvrier avant",QMessageBox::Ok);
            ui->cinLE->setFocus();
            return;
        }
        report->addParameter("cin",cin);

        report->addParameter("nom",ui->persoTable->item(ui->persoTable->currentRow(),0)->text());
        report->addParameter("prenom",ui->persoTable->item(ui->persoTable->currentRow(),1)->text());
    }


    if (repFile=="payMois.xml"){
        report->addParameter("month",ui->moisCB->currentText());
        report->addParameter("table",QDate::currentDate().toString(QString("%1-yyyy").arg(ui->moisCB->currentIndex()+1)));
    }
    report->setReportFile(repFile );

    report->runReportToPreview();


    if ( !report->hasError() ) {
        NCReportPreviewWindow *pv = new NCReportPreviewWindow();
        pv->setOutput( (NCReportPreviewOutput*)report->output() );
        pv->setWindowModality( Qt::ApplicationModal );
        pv->setAttribute( Qt::WA_DeleteOnClose );
        pv->show();
    }
    else
        qDebug()<<report->lastErrorMsg();
}

void MainWindow::printAbsMois(){
    printTable("abs.xml");
}
void MainWindow::printAbsEmp(){
    printTable("absEmp.xml");
}
void MainWindow::printPayMois(){
    printTable("payMois.xml");
}
void MainWindow::printPayEmp(){
    printTable("payEmp.xml");
}
void MainWindow::print(){

    printTable("perso.xml");


}

void MainWindow::showSettings(){
    SqlDatabaseDialog d;
    d.exec();
    //dbConnect();
}

void MainWindow::saisirAbs(){

    b=new DialogAbs (this);
    b->show();
    QDate lastDay=QDate(QDate::currentDate().year(),ui->moisCB->currentIndex()+1,1);

    b->setMonth(QDate(QDate::currentDate().year(),ui->moisCB->currentIndex()+1,16),QDate(QDate::currentDate().year(),ui->moisCB->currentIndex()+2,15));//lastDay.daysInMonth()));

    b->showAbs(QDate::currentDate().year(),ui->moisCB->currentIndex()+1);
}

void MainWindow::createCompleters(){
    nomList= perso.nom;
    prenomList=perso.prenom;
    posteList=perso.poste;

    nomList.removeDuplicates();
    prenomList.removeDuplicates();
    posteList.removeDuplicates();

    nomComp= new QCompleter(nomList, this);
    prenomComp= new QCompleter(prenomList, this);
    posteComp= new QCompleter(posteList, this);
    //
    //prenomComp->setCompletionMode(QCompleter::InlineCompletion);
    prenomComp->setCaseSensitivity(Qt::CaseInsensitive);
    nomComp->setCaseSensitivity(Qt::CaseInsensitive);
    posteComp->setCaseSensitivity(Qt::CaseInsensitive);
    ui->nameLE->setCompleter(nomComp);
    ui->surNameLE->setCompleter(prenomComp);
    ui->posteLE->setCompleter(posteComp);

}

void MainWindow::dbConnect() {

    db = QSqlDatabase::addDatabase(map.value("driver").toString(),"qt_sql_default_connection");
    /// @note we use the defaut connetion name ="qt_sql_default_connection"
    db.setHostName(map.value("host").toString());
    db.setPort(map.value("port").toInt());
    db.setDatabaseName(map.value("databaseName").toString());
    //if (ui->userLE->text()=="" || ui->passLE->text()=="") {
    //  QMessageBox::critical(0,"Connexion Impossible","Veuillez saisir les données de connexion",QMessageBox::Ok);
    //}
    db.setUserName(map.value("user").toString());
    db.setPassword(map.value("password").toString());
    dbConnOk = db.open();
    if (!dbConnOk) {
        QMessageBox::critical(0,"Éhec de connexion",db.lastError().text(),QMessageBox::Ok);
        enableNavigation(false);
        return;
    }
    ui->statusBar->showMessage(msg.arg("Connecté à la base de données"));
    ui->connectPB->setEnabled(false);
    ui->persoPB->setEnabled(true);
    ui->startPB->setEnabled(true);
    enableNavigation(true);
    editMode=false;
    getRecords();
    editMode=true;

}


void MainWindow::setEdit(bool state){
    editMode=state;
    if (state){
        ui->editPB->setIcon(QIcon(":32x32/document-decrypt.png"));
        editMode=false;
        perso.setMode(true);
        getRecords();        
        editMode=true;
    }
    else{
        ui->editPB->setIcon(QIcon(":32x32/document-encrypt.png"));
        perso.setMode(false);
        getRecords();        
    }

}

    void MainWindow::FindPersoSur(){

QList<QTableWidgetItem *> match=ui->persoTable->findItems(ui->surNameSearch->text(),Qt::MatchStartsWith);
foreach (QTableWidgetItem *cell, match){
    ui->persoTable->selectRow(cell->row());
}

}





void MainWindow::showFiche(QModelIndex index){
    /// show values on lineEdits
    current.seek(index.row());
    showVals();

    QTableWidgetItem *newItem;
    /// clear any previously displayed Fiche de paye
    for (int i=0; i <=11; i++) {
        newItem = new QTableWidgetItem("",0);
        ui->ficheTable->setItem(i, 0, newItem);
    }
    //perso.clearTable(ui->ficheTable);
    /// maybe we have to show the text Fields on line Edits
    fiche=QSqlQuery("SELECT * FROM Salaires where cin="+ui->persoTable->item(index.row(),3)->text(),db);

    /// Get the record (should be unique!)
    while (fiche.next()){
        for (int i=1; i <=12; i++) {
            newItem = new QTableWidgetItem(fiche.value(i).toString(),0);
            ui->ficheTable->setItem(i-1, 0, newItem);
        }
    }

}



void MainWindow::showAbs(){
    getValues();

    if (cin==""){
        QMessageBox::critical(0,"Impossible","Veuillez sélectionner un ouvrier avant",QMessageBox::Ok);
        ui->cinLE->setFocus();
        return;
    }
    if (!dbConnOk){
        QMessageBox::critical(0,"Impossible","Veuillez d'abord vous connecter avant",QMessageBox::Ok);
        ui->connectPB->setFocus();
        return;
    }
    abs= new Dialog(this);
    abs->show();

    QDate lastDay=QDate(QDate::currentDate().year(),ui->moisCB->currentIndex()+1,1);

    abs->setMonth(QDate(2000,QDate::currentDate().month()+1,16),QDate(QDate::currentDate().year(),ui->moisCB->currentIndex()+2,15));//,lastDay.daysInMonth()));
    abs->setCin(cin,nom+' '+prenom,baseSal.toDouble());
    abs->showAbs(QDate::currentDate().year(),ui->moisCB->currentIndex()+1);
    abs->calcSal();
    db.setDatabaseName("paye");
}


void MainWindow::getValues() {
    nom=ui->nameLE->text();
    prenom=ui->surNameLE->text();
    cnss=ui->cnssLE->text();
    cin=ui->cinLE->text();
    baseSal=ui->salaireSB->text();
    poste=ui->posteLE->text();
    dateNais=ui->dateEdit->text();
    ID=ui->IDSB->text();
}

QString MainWindow::getCellValue(int r, int c){
    return ui->persoTable->item(r,c)->text();
}


void MainWindow::getRecords()  {
    current=QSqlQuery("SELECT* FROM Employ order by "+fieldOrder,db);
    msg=QString(tr("Personnel :%1 personnes")).arg(current.size());
    ui->infoLBL->setText(msg);

    perso.showPerso(ui->persoTable,fieldOrder);
    createCompleters();
    if (ui->persoTable->rowCount()==0){
        ui->nextPB->setEnabled(false);
        ui->previousPB->setEnabled(false);
    }
    else {
        ui->nextPB->setEnabled(true);
        ui->previousPB->setEnabled(true);
    }
}


void MainWindow::enableNavigation(bool con){
    ui->previousPB->setEnabled(con);
    ui->nextPB->setEnabled(con);
    ui->newPB->setEnabled(con);
    ui->delPB->setEnabled(con);
    ui->editPB->setEnabled(con);
    ui->startAB->setEnabled(con);
    ui->triCB->setEnabled(con);
    ui->surNameSearch->setEnabled(con);

}

void MainWindow::checkChanges(int row,int coloumn){

    if (!editMode)
        return;

qDebug()<<"checking for changes";
    /// connect all text fields TextChanged signal to a routine that will be used a s a flag
    QMessageBox msgBox;
    msgBox.setWindowTitle(tr("Confirmation"));
    msgBox.setText(tr("Voulez vous appliquer les changments?"));
    msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
    //msgBox.setDefaultButton(QMessageBox::No);
    int ret=msgBox.exec();

    /// @todo: Add option for safety questions confirm
    if (ret!=QMessageBox::Yes){
        /// We restore the table to its pervious state @todo: update only the changed cell!
       // editMode=false;
        perso.setMode(true);
        getRecords();
      //  editMode=true;
        return;
    }
    /// It's time to update the changes!
    QString field;
    switch (coloumn){
    case 0:
        field="ID";break;
    case 1:
        field="nom";break;
    case 2:
        field="prenom";break;
    case 3:
        field="cnss";break;
        /// CIN field can't be changed !!
    case 5:
        field="salaire";break;
    case 6:
        field="poste";break;
    case 7:
        field="`date naissance`";break;
    }
    //qDebug()<<field<<getCellValue(row,coloumn);
    operation=QSqlQuery(db);
    if(!operation.exec("UPDATE Employ SET "+field+"='"+getCellValue(row,coloumn)+"' WHERE CIN= "+ui->cinLE->text())){
        qDebug()<<"Operation non reussie"<<operation.lastError().text();
    }

}



void MainWindow::newRec() {
    bool oldMode;

    getValues();

    if (nom=="" || prenom==""|| cnss==""|| cin=="" || baseSal=="0.000") {
        QMessageBox::critical(0,"Données incomplètes","Veuillez saisir toutes les données",QMessageBox::Ok);
        return;
    }
    operation=QSqlQuery(db);
    if(!operation.exec("INSERT INTO Employ (nom, prenom,CNSS,CIN,salaire,poste,`date naissance`,ID) VALUES ('"+nom+"','"+prenom+"','"+cnss+"','"+cin+"','"+baseSal+"','"+poste+"','"+dateNais+"','"+ID+"')")){
        if (operation.lastError().text().contains("Duplicate"))
            QMessageBox::critical(0,"Opération non réalisée","Impossible d'ajouter l'employe :\n Il existe déjà un autre avec le mm CIN",QMessageBox::Ok);
        else
            QMessageBox::critical(0,"Opération non réalisée","Impossible d'ajouter l'employe :\n"+operation.lastError().text(),QMessageBox::Ok);
        return;
    }
    /// Have to update old queries now
  //  oldMode=editMode;
   // editMode=false;
    /// reEnable previous and next buttons if no more records

    getRecords();    
  //  editMode=oldMode;
}

void MainWindow::del() {

    /// Have to remove all the associated abscences also??
    bool oldMode;
    QMessageBox msgBox;
    msgBox.setWindowTitle("Confirmation");
    /// TODO . ADD EMPLOYE NAME
    msgBox.setText(tr("Voulez vous vraiment supprimer %1 ?").arg(ui->nameLE->text()));
    msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
    msgBox.setDefaultButton(QMessageBox::No);
    int ret=msgBox.exec();

    /// @todo: Add option for safety questions confirm
    if (ret!=QMessageBox::Yes){
        return;
    }
    operation=QSqlQuery(db);
    /// HAVE to delete all other related DB records ??
    if(!operation.exec("DELETE FROM Employ where `CIN` ="+ui->cinLE->text())){
        QMessageBox::critical(0,"Opération non  réalisée","Impossible d'ajouter l'employé :\n"+operation.lastError().text(),QMessageBox::Ok);
        return;
    }

    /// Have to update old queries now
    //oldMode=editMode;
    //editMode=false;
    getRecords();    
  //  editMode=oldMode;



}

void MainWindow::showPersonnel(){
    if (dbConnOk){
        perso.show();
        perso.showPerso();
    }
}



void MainWindow::previous() {
    current.previous();
    if (current.at()==QSql::BeforeFirstRow ){
        ui->statusBar->showMessage("Premier enregistrement atteint");
        msg="Premier enregistrement atteint";
        ui->infoLBL->setText(msg);
        return;
    }
    showVals();
}


void MainWindow::next() {
    // We roll back if we are on the last/dfirst records

    current.next();
    if ( current.at()==QSql::AfterLastRow ){
        ui->statusBar->showMessage("Dernier enregistrement atteint");
        msg="Dernier enregistrement atteint";
        ui->infoLBL->setText(msg);
        return;
    }
    showVals();
}

void MainWindow::showVals() {
    ui->statusBar->clearMessage();
    /// to select the whole row
    ui->persoTable->selectRow(current.at());

    ///showFiche((ui->persoTable->currentItem())->row());
    msg=QString("Enregistrement :%1 ").arg(current.at()+1);
    ui->statusBar->showMessage(msg);
    ui->nameLE->setText(current.value(0).toString());
    ui->surNameLE->setText(current.value(1).toString());
    ui->cnssLE->setText(current.value(2).toString());
    ui->cinLE->setText(current.value(3).toString());
    ui->salaireSB->setValue(current.value(4).toDouble());
    ui->posteLE->setText(current.value(5).toString());
    ui->dateEdit->setDate(current.value(7).toDate());
     ui->IDSB->setValue(current.value(8).toInt());
}

MainWindow::~MainWindow()
{
    delete ui;
}
